# -*- coding: utf-8 -*-
# @Date    : 2024/2/2
# @Author  : zouy
# @Email: 874112501@qq.com
import subprocess
from functools import partial
from urllib.parse import urljoin
import string
import re
import json

import requests
from loguru import logger
import execjs

from util import *

subprocess.Popen = partial(subprocess.Popen, encoding='utf-8')


def get_jsonp(text):
    try:
        jsonp_str = re.search(r"\((.*)\)", text, re.S).group(1)
    except Exception as e:
        jsonp_str = text
    return json.loads(jsonp_str)


def get_now():
    return str(int(time.time() * 1000))


def get_session():
    session = requests.Session()
    session.headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36",
        # 'Accept': '*/*',
        # 'Accept-Language': 'zh-CN,zh;q=0.9',
        # 'Cache-Control': 'no-cache',
        # 'Connection': 'keep-alive',
        # 'Pragma': 'no-cache',
        "cookie": "_ga=GA1.1.997389011.1701204600; __gads=ID=fac603d8ef4363ba:T=1701204600:RT=1701204600:S=ALNI_MYUs0UbbzSCaMJYAzWakAK8mCzkGw; __gpi=UID=00000c9c2977416d:T=1701204600:RT=1701204600:S=ALNI_MZcmDKIQuqpG8gxnhI_Osxez1cbaA; acw_tc=2760820e17024359895741737e558d400a681a0c4076333064dde6b5749e3c; PHPSESSID=36ba3f7d0ba681bce18a35101133c975; Hm_lvt_e23800c454aa573c0ccb16b52665ac26=1701204600,1702347400,1702435992; Hm_lpvt_e23800c454aa573c0ccb16b52665ac26=1702436057; _ga_MJYFRXB3ZX=GS1.1.1702435991.5.1.1702436058.0.0.0; ssxmod_itna=eqAxRQq7whqBPxtDyDG2iDuAjG8YDRrwB2YQlODGXxX5DZDiqAPGhDCShIDD5dT7l7E5paqcARqvaZWiApPbLAW7ppLNb4B3DEx0==KznMxGG0xBYDQxAYDGDDPDoZPD1D3qDkD7g1ZlndtDm4GWzqGfDDoDYS6nDitD4qDBmEdDKqGgzwxdmu4D0u4bVYm3tm2UGeNQ6TqKTB=DjTTD/RqkVmRkuc4V7e9e3CpnDB=wxBQZ0MXX0eDHmq0Z3neARBxGQAQN8rwxSoe4mSEYQG4NQGwilG46F3evB0DGG0z6xDfxjD+b8iDD; ssxmod_itna2=eqAxRQq7whqBPxtDyDG2iDuAjG8YDRrwB2YQeA6ne3D/ex0x7P=60ON3Nwyx6OD8h0jxKCEiYrwUAPmbr=UQYCiWHFq4mOFfVCgrY6e0f8E7Ym42ZpS0+eI3CLLux6FiU9O56wHfsHPBHqFHaAO7io2n14gPGuoBheS7rUnBO2mAaWQ0pF194sRHrWCwdD6BrqGTqP1mxh4cHdWW70+yj5r0OCCcDhZuLA8pKxsn1tPR+FADxXC9OzlEPnAhHYsTropIFySaCvgcnz66PAtTA3A9k+SFUpc/SoEUCh3agQtGBlZlpuzpGeLn=jMip51owaw48GPPiGr0XY0mG0Mimihj3erEC5GCXdrqQ/oiPi3KiLPifYbxFmWK2BnY0=fNUvVQ3kK3/QuOBXKOTsFeN2RSxWq026nXNg0iDuZaE7GQatqAUuxAEhFfurR=it4IxZ7pzGpqZcjGuoxoFbd4fDhbRiB9Hzu8CalliXKtbc0gz4qP9lbPwrhWDG2exx+2SCfKj0F42OtC+2b28Q8fvTxxW87IlDoICtzKsS0Q4h5D08DijuZhf2pen5LfcZEodlQOTYLIKLbMzBE3mKdjqEmGfavTe5LKU7Ek3ACoGpin54Bx15q8XhxYD===",
        'Referer': 'https://segmentfault.com/user/forgot',
    }
    return session


def ft_register_slide(session):
    """1.1 注册获取challenge和gt"""
    # url = 'https://www.geetest.com/demo/gt/register-slide-official?t={}'.format(get_now())
    url = 'https://segmentfault.com/gateway/geetest/token'
    res = session.get(url)
    data = res.json()
    return data['gt'], data['challenge']


def ft_gettype(session, gt):
    """1.2 获取fullpage.js和slide.js和click.js等文件网址
     setCookie:GeeTestUser
    """
    url = 'https://api.geetest.com/gettype.php'
    params = {
        "gt": gt,
        "callback": 'geetest_' + get_now(),
    }
    res = session.get(url, params=params)
    data = get_jsonp(res.text)

    return data


def get16randomStr(k):
    return ''.join(random.choices(string.digits + 'abcde', k=k))


def ft_get_php(session, gt, challenge):
    """1.3 第一个w,返回c(不变)[ 12, 58, 98, 36, 43, 95, 62, 15, 12 ]和s"""
    url = 'https://api.geetest.com/get.php'
    w = ctx.call('generate_w1', gt, challenge, random16Key)
    params = {
        "gt": gt,
        "challenge": challenge,
        "lang": "zh-cn",
        "pt": "0",
        "client_type": "web",
        "w": w,
        "callback": "geetest_" + get_now()
    }
    res = session.get(url, params=params)
    data = get_jsonp(res.text)

    return data


def sc_ajax(session, gt, challenge, c, s):
    """2.1 第二个w，返回{"result": "slide"}
    Set-Cookie: GeeTestAjaxUser
    """
    url = "https://api.geevisit.com/ajax.php"
    track = get_track()
    w2_params = {
        'gt': gt,
        'challenge': challenge,
        'c': c,
        's': s,
        'track': track,
        'random16Key': random16Key
    }
    w = ctx.call('generate_w2', w2_params)
    params = {
        "gt": gt,
        "challenge": challenge,
        "lang": "zh-cn",
        "pt": "0",
        "client_type": "web",
        "w": w,
        "callback": "geetest_" + get_now()
    }
    res = session.get(url, params=params)
    data = get_jsonp(res.text)

    return data


def sc_get_php(session, gt, challenge):
    """2.2 返回验证码图片网址及新challenge值和s值和gct_path文件等
    set-cookie: GeeTestUser
    """
    url = "https://api.geevisit.com/get.php"
    params = {
        "is_next": "true",
        "type": "slide3",
        "gt": gt,
        "challenge": challenge,
        "lang": "zh-cn",
        "https": "false",
        "protocol": "https://",
        "offline": "false",
        "product": "embed",
        "api_server": "api.geevisit.com",
        "isPC": "true",
        "autoReset": "true",
        "width": "100%",
        "callback": "geetest_" + get_now(),
    }
    res = session.get(url, params=params)
    data = get_jsonp(res.text)
    return data


def calc_third_w(gt, challenge, distance, passtime, getphp_c, getphp_s, gj_array):
    """生成拖动滑块，发送请求的第三个w参数"""

    params = {
        'distance': distance,
        'passtime': passtime,
        'track': gj_array,
        'c': getphp_c,
        's': getphp_s,
        'gt': gt,
        'challenge': challenge,
        'random16Key': random16Key,
    }
    print(params)
    result = ctx.call('generate_w3', params)

    logger.info(result)
    return result  # ['w']


def td_ajax_php(session, gt, challenge, getphp_c, getphp_s):
    """3 .拖动滑块,返回validate
    """
    distance = get_x()
    # gj_array, passtime = get_slide_track(distance-10)
    from GTrace import GTrace
    gtrace = GTrace()
    # -10，图片不是从头部开始的
    distance, track = gtrace.get_mouse_pos_path(distance - 10)

    w = calc_third_w(gt, challenge, track[-1][0], track[-1][2], getphp_c, getphp_s, gj_array=track)

    url = "https://api.geevisit.com/ajax.php"
    params = {
        "gt": gt,
        "challenge": challenge,
        "lang": "zh-cn",
        "$_BCN": "0",
        "client_type": "web",
        "w": w,
        "callback": "geetest_" + get_now()
    }
    res = session.get(url, params=params)
    data = get_jsonp(res.text)
    return data


def get_token(session):
    url = 'https://segmentfault.com/user/forgot'
    r = session.get(url)
    text = r.text
    token = re.search(r'"key":\s*"(.*?)"', text, re.S).group(1)
    logger.info('token >>>' + token)
    session.headers['token'] = token


def main():
    ss = get_session()
    time.sleep(1)

    get_token(ss)

    # ********** 一.进入验证码页面  **********
    gt, challenge = ft_register_slide(ss)
    # gt: 019924a82c70bb123aae90d483087f94  challenge: 27ba0fbf47da77d6fcc65e3484eaedd4
    logger.info(f"1.1 register_slide获取gt: {gt}  challenge: {challenge}")
    time.sleep(2)

    # gettype_data = ft_gettype(ss, gt=gt)
    # fullpage = gettype_data['data']['fullpage']
    # slide = gettype_data['data']['slide']
    # # fullpage.9.1.8-bfget5.js   slide.7.9.2.js
    # logger.info(f'1.2 gettype获取js版本，fullpage: {fullpage}  slide: {slide}')

    getphp_data = ft_get_php(ss, gt=gt, challenge=challenge)
    c, s = getphp_data['data']['c'], getphp_data['data']['s']
    logger.info(f'1.3 get.php获取c: {c}   s: {s}')  # c: [12, 58, 98, 36, 43, 95, 62, 15, 12]   s: 2a6e744e
    time.sleep(3)
    # ********** 二.点击验证按钮  **********
    ajax_data = sc_ajax(ss, gt=gt, challenge=challenge, c=c, s=s)
    logger.info(f'2.1 ajax.php获取 {ajax_data}')  # {'status': 'success', 'data': {'result': 'slide'}}
    validate = ajax_data['data'].get('validate')
    time.sleep(3)
    if validate:
        logger.info('未出现二次验证，直接发送验证码')
        # ajaxphp_data = td_ajax_php(ss, gt=gt, challenge=challenge, getphp_c=c, getphp_s=s)
        # {'status': 'error', 'error': 'not userresponse', 'user_error': '网络不给力', 'error_code': 'error_13'}
        # logger.success(f'3 ajax.php获取validate: {ajaxphp_data}')
        send_msg(ss, validate, challenge)
        return

    getphp_data = sc_get_php(ss, gt=gt, challenge=challenge)
    new_challenge = getphp_data['challenge']
    getphp_c = getphp_data['c']
    getphp_s = getphp_data['s']
    logger.info(f'2.2 get.php获取 {getphp_data}')
    time.sleep(2)

    # 下载滑块验证码图片
    static_url = "https://static.geetest.com"
    bg_url = urljoin(static_url, getphp_data["bg"])
    fullbg_url = urljoin(static_url, getphp_data["fullbg"])
    slice_url = urljoin(static_url, getphp_data["slice"])

    download_img(ss, "bg.jpg", bg_url)
    download_img(ss, "fullbg.jpg", fullbg_url)
    download_img(ss, "slice.jpg", slice_url)

    # 还原图片
    trun_back("bg.jpg")
    trun_back("fullbg.jpg")
    time.sleep(3)
    # ********** 三.拖动滑块  **********
    ajaxphp_data = td_ajax_php(ss, gt=gt, challenge=new_challenge, getphp_c=getphp_c, getphp_s=getphp_s)
    # {'status': 'error', 'error': 'not userresponse', 'user_error': '网络不给力', 'error_code': 'error_13'}
    logger.success(f'3 ajax.php获取validate: {ajaxphp_data}')
    time.sleep(2)
    send_msg(ss, ajaxphp_data['validate'], new_challenge)


def send_msg(session, validate, challenge):
    url = 'https://segmentfault.com/gateway/phone/code'
    payload = {
        "phone": input('请输入需要重置密码的手机号').strip(),
        "geetest_challenge": challenge,
        "geetest_validate": validate,
        "geetest_seccode": validate + "|jordan"
    }
    r = session.post(url, json=payload)

    logger.info(r.json())


if __name__ == '__main__':
    with open(os.path.join(DIR_PATH, "w3.js"), 'r', encoding='utf-8') as f:
        js_code = f.read()
    ctx = execjs.compile(js_code)
    random16Key = get16randomStr(16)
    main()
